package cn.gov.cus.rmftquartz.common.utils;

import cn.gov.cus.rmftquartz.entity.ManifestChkNewVo;
import com.google.common.base.Strings;
import com.mongodb.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.regex.Pattern;

import static java.util.regex.Pattern.compile;

@Component
public class MongoDBUtil {
    private static final Logger _log = LoggerFactory.getLogger(MongoDBUtil.class);

    @Value("${datasource.mongodb.ruleengine.url.ip}")
    private String dbIp;

    @Value("${datasource.mongodb.ruleengine.url.port}")
    private int port;

    public static void main(String[] args){
        Mongo mongo = new MongoDBUtil().getMongo();
    }

    public Mongo getMongo(){
        Mongo mongo = null;
        try{
            mongo=new Mongo(dbIp,port);//mongo-java-driver-2.9.3.jar!\com\mongodb\Mongo.class
        }catch(Exception e){//此处捕获UnknownHostException报错因为上面Mongo引入的jar包不同。或者直接Exception。
            _log.error(ExceptionHelper.getExMsg(e));
            System.out.println("连接MongoDB错误！");
        }
        return mongo;
    }

    /**
     * 使用去mongoDb查一个数据
     * eg：String rule_id = findFromMongo("ruleEngine","hgHashTable","hashcode",hashcode,"rule_id");
     * MongoDb中的一条查询语句：db.hgHashTable.find({hashcode:'d7fh23yf2fd23jf3yy2'})
     * @param dbName 某一个IP下的一个库名。
     * @param tName 库里的一个表名。
     * @param key 查询条件中的key。
     * @param keyValue 查询条件中的value。
     * @param resultKey 在查询出的结果对象中要取值的属性名。跟查询时的key一样，都是mongoDB库表中的一个字段。MongoDB库中的存储方式是一张表中有很多个对象，一个对象中都是key：value方式存的数据，没有固定表字段。
     * @return
     */
    public String findFromMongo(String dbName,String tName,String key,String keyValue,String resultKey){
        Mongo mongo = this.getMongo();
        DB ruleEngineDB = mongo.getDB(dbName);
        DBCollection dbCollection = ruleEngineDB.getCollection(tName);

        BasicDBObject query = new BasicDBObject(key,keyValue);
        DBCursor dbCursor = dbCollection.find(query);

        String result="";
        //while(dbCursor.hasNext()){//循环查到的多个值
        if(dbCursor.hasNext()){//如果对于查到的值只需要取一个，直接if就行。否则while。
            BasicDBObject obj = (BasicDBObject)dbCursor.next();
            if(obj != null){
                result = obj.getString(resultKey);
            }
        }
        mongo.close();//使用完关闭连接。
        return result;
    }

    public ArrayList<String> findRfered(String enName){
        Mongo mongo = getMongo();
        DB ruleEngineDB = mongo.getDB("ruleEngine");
        DBCollection hgruleCollection = ruleEngineDB.getCollection("hg_rule");

        Pattern pattern = compile("\\$"+enName+"\\$");
        DBCursor cursor = hgruleCollection.find(new BasicDBObject("drl",pattern));
        ArrayList<String> ruleList = new ArrayList<>();
        while (cursor.hasNext()){
            DBObject next = cursor.next();
            if("启用".equals(next.get("state"))){
                ruleList.add(next.get("cnname").toString());
            }
        }
        return  ruleList;
    }

    public ArrayList<String> findRules(String enName){
        ArrayList<String> ruleList = new ArrayList<>();
        Mongo mongo = getMongo();
        DB ruleEngineDB = mongo.getDB("ruleEngine");
        DBCollection hgruleCollection = ruleEngineDB.getCollection("hg_rule");

        DBCursor cursor = hgruleCollection.find();
        while (cursor.hasNext()){
            DBObject next = cursor.next();
            if(next.get("state").toString().contains(enName)){
                ruleList.add(next.get("cnname").toString()+"#"+next.get("createtime"));
            }
        }
        return  ruleList;
    }

    /**
     * 将一个list里的所有对象的值插入MongoDB.
     * @param list
     */
    public void insertToMongoDemo(List<ManifestChkNewVo> list){
        Mongo mongo = getMongo();
        DB ruleEngineDB = mongo.getDB("ruleEngine");
        DBCollection ruleCollection =  ruleEngineDB.getCollection("think_businesscase");
        List<DBObject> dbObjects = new ArrayList<>();
        for(ManifestChkNewVo o:list){
            BasicDBObject paraFieldDbo = new BasicDBObject();
            paraFieldDbo.append("owner_id","0")
                    .append("cname",o.getH2000ChkNewUser())
                    .append("ename","abc")
                    .append("type","属性")
                    .append("createtime",Integer.parseInt((System.currentTimeMillis()+"").substring(0,10)))
                    .append("updatetime",Integer.parseInt((System.currentTimeMillis()+"").substring(0,10)))
                    .append("user_id",null);
            dbObjects.add(paraFieldDbo);
        }
        ruleCollection.insert(dbObjects);
        mongo.close();
    }

    public void insertToMongoDemo2(ManifestChkNewVo vo){
        Mongo mongo = getMongo();
        DB ruleEngineDB = mongo.getDB("ruleEngine");
        DBCollection ruleCollection =  ruleEngineDB.getCollection("think_businesscase");
        BasicDBObjectBuilder dbObjectBuilder = BasicDBObjectBuilder.start();
        dbObjectBuilder.append("owner_id","0")
                .append("cname",vo.getH2000ChkNewUser())
                .append("ename","0004")
                .append("type","属性")
                .append("default","")
                .append("num",vo.getPageNum()+"")
                .append("createtime",Integer.parseInt((vo.getCreateDate().getTime()+"").substring(0,10)))
                .append("updatetime",Integer.parseInt((System.currentTimeMillis()+"").substring(0,10)))
                .append("user_id",null)
                .append("javaurl","/BOM/"+vo.getEntryData()+".java");

        ruleCollection.insert(dbObjectBuilder.get());
        mongo.close();
    }

    /**
     * 因为长度限制，将大批数据分成一小批一小批的插入。
     * @param paraDatas
     */
    public void insertToMongoDemo3(List<LinkedHashMap<String,Object>> paraDatas){
        Mongo mongo = getMongo();
        DB hgDB = mongo.getDB("hg");
        DBCollection collection = hgDB.getCollection("think_businesscase");
        List<DBObject> dbObjects = new ArrayList<>(paraDatas.size());
        for(int i=0;i<paraDatas.size();i++){
            BasicDBObject dbo = new BasicDBObject();
            dbo.putAll(paraDatas.get(i));
            dbo.removeField("APPLY_ID");
            dbo.removeField("STATUS");
            dbo.removeField("rownum");
            dbo.append("visibility","1");
            dbObjects.add(dbo);
            /**
             * 分批代码！！！
             */
            if(dbObjects.size()>5000||i==paraDatas.size()-1){
                collection.insert(dbObjects);
                dbObjects.clear();
            }
        }
        mongo.close();
    }

    /**
     * 删除MongoDB中ruleEngine库中think_bussinesscase集合里的相关表和属性记录
     */
    public void deleteFromMongoDemo(int paraListId){
        Mongo mongo = getMongo();
        DB ruleEngineDB = mongo.getDB("ruleEngine");
        BasicDBObject paraListQuery = new BasicDBObject("$and", Arrays.asList(new BasicDBObject("id",paraListId),new BasicDBObject("hgobjecttype_id_","0004")));
        BasicDBObject paraFieldQuery = new BasicDBObject("$and", Arrays.asList(new BasicDBObject("pid",paraListId+""),new BasicDBObject("hgobjecttype_id_","0002")));
        BasicDBObject query = new BasicDBObject("$or",Arrays.asList(paraListQuery,paraFieldQuery));
        DBCollection thinkBusinesscase = ruleEngineDB.getCollection("think_businesscasse");
        DBCursor dbCursor = thinkBusinesscase.find(query);
        while (dbCursor.hasNext()){
            DBObject paraFieldDbo = dbCursor.next();
            thinkBusinesscase.remove(paraFieldDbo);
        }
        mongo.close();
    }

    public void deleteData(String[] ids){
        Mongo mongo = getMongo();
        DB hgDB = mongo.getDB("hg");
        DBCollection dataCollection = hgDB.getCollection("think_businesscase");
        for(String uuid:ids){
            dataCollection.remove(new BasicDBObject("UUID",uuid));
        }
    }

    /**
     * 根据参数表名更新规则版本号
     * 若无版本号则添加为“0”，若有则加1
     * @param tabName 被引用参数表表名
     */
    public void updateRule(String tabName){
        Mongo mongo = getMongo();
        DB ruleEngineDB = mongo.getDB("ruleEngine");
        DBCollection hgruleCollection = ruleEngineDB.getCollection("hg_rule");

        Pattern pattern = Pattern.compile("\\$"+tabName+"\\$");
        DBCursor cursor = hgruleCollection.find(new BasicDBObject("drl",pattern));
        while(cursor.hasNext()){
            DBObject dbObject = cursor.next();
            String version = (String)dbObject.get("version");
            if(!Strings.isNullOrEmpty(version)){
                int versionNo=(int)Double.parseDouble(version);
                versionNo++;
                version=versionNo+"";
            }else{
                version="0";
            }
            hgruleCollection.update(new BasicDBObject("drl",pattern).append("enname",dbObject.get("enname")),new BasicDBObject("$set",new BasicDBObject("version",version)),false,true);
        }
    }

}
